//
// Calc.cpp for calc 206 in /home/druart_p/Work/math/my-math-epi/206
//
// Made by pierrick druart
// Login   <druart_p@epitech.net>
//
// Started on  Wed May  9 14:45:55 2012 pierrick druart
// Last update Sun May 13 21:03:05 2012 pierrick druart
//

#include	"Calc.hh"

// Construtor & Destructor

Calc::Calc(const std::string & file)
{
  getValueFromFile(file);
  lexValue();
  affRes();
}

Calc::~Calc() {}

// Get File Value

void		Calc::getValueFromFile(const std::string & file)
{
  std::string	line;
  const char	*test = file.c_str();
  std::ifstream myfile(test);

  if (myfile.is_open())
    {
      while (myfile.good())
	{
	  getline(myfile, line);
	  this->value.push_back(line);
	}
      myfile.close();
    }
}

void		Calc::affRes()
{
  std::cout << "\t Mathematique" << std::endl << std::endl;
  std::cout << std::setprecision(5) << "Moyenne arithmetique\t" << (this->ari = (this->ari / this->total)) << std::endl;
  std::cout << std::setprecision(5) << "Moyenne Quadratique\t" << (this->quadra = (sqrt(this->quadra / this->total))) << std::endl;
  std::cout << std::setprecision(5) << "Moyenne Geometrique\t" << (this->geo = (pow(this->geo, (1.0 / this->total)))) << std::endl;
    std::cout << std::setprecision(4) << "Moyenne Harmonique\t" << (this->geo = (this->total / this->harmo)) << std::endl;
  std::cout << std::setprecision(5) << "Mediane\t\t\t" << (this->med = mediane()) << std::endl;
  std::cout << std::setprecision(5) << "Mode\t\t\t" << this->mod << std::endl;
  std::cout << std::setprecision(5) << "Variance\t\t" << (this->var = ((this->var / this->total) - pow((this->ari), 2))) << std::endl;
  std::cout << std::setprecision(5) << "Ecart-Type\t\t" << sqrt(this->var) << std::endl;
  std::cout << std::setprecision(5) << "Ecart Moyen\t\t" << ecartMoyen(this->ari) << std::endl;
  std::cout << std::setprecision(5) << "Ecart Median\t\t" << ecartMedian(this->med) << std::endl;
}

void		Calc::init()
{
  this->ari = 0;
  this->total = 0;
  this->quadra = 0;
  this->geo = 1;
  this->harmo = 0;
  this->med = 0;
  this->mod = 0;
  this->tmp = 0;
  this->tmp2 = 0;
  this->var = 0;
  this->eMoy = 0;
  this->eMed = 0;
  this->max = 0;
}

void		Calc::repartition(int val, int eff)
{
  moyenneArithmetique(val, eff);
  moyenneQuadratique(val, eff);
  moyenneGeometrique(val, eff);
  moyenneHarmonique(val, eff);
  mode(val, eff);
  variance(val, eff);
}

void		Calc::lexValue()
{
  std::list<std::string>::iterator it;
  int		nbr = 0;

  init();
  for (it = this->value.begin();it != this->value.end(); ++it)
    {
      if (nbr == 0)
	{
	  std::istringstream	iss(*it);
	  iss >> nbr;
	  ++it;
	}
      int		val = 0;
      int		eff = 0;
      std::stringstream	temp(*it);
      std::string	valeur;
      std::string	effectif;
      temp >> valeur;
      temp >> effectif;
      std::istringstream	iss1(valeur);
      std::istringstream	iss2(effectif);
      iss1 >> val;
      iss2 >> eff;
      if (val != 0 && eff != 0)
	repartition(val, eff);
      this->total += eff;
      if (val != 0)
	this->max = val;
    }
}

void		Calc::moyenneArithmetique(int val, int eff)
{
  this->ari = (val * eff) + this->ari;
}

void		Calc::moyenneQuadratique(int val, int eff)
{
  this->quadra = ((val * val) * eff) + this->quadra;
}

void		Calc::moyenneGeometrique(int val, int eff)
{
  this->geo = pow(val, eff) * this->geo;
}

void		Calc::moyenneHarmonique(int val, int eff)
{
  this->harmo = (1.0 / val * eff) + this->harmo;
}

double		Calc::mediane()
{
  int		i = 0;
  int		ret = 0;
  int		nbr = 0;
  double	save;
  std::list<std::string>::iterator it;

  if (this->total % 2 == 0)
    {
      ret = this->total / 2;
      for (it = this->value.begin();it != this->value.end(); ++it)
	{
	  if (nbr == 0)
	    {
	      std::istringstream	iss(*it);
	      iss >> nbr;
	      ++it;
	    }
	  int		val = 0;
	  int		eff = 0;
	  std::stringstream	temp(*it);
	  std::string	valeur;
	  std::string	effectif;
	  temp >> valeur;
	  temp >> effectif;
	  std::istringstream	iss1(valeur);
	  std::istringstream	iss2(effectif);
	  iss2 >> eff;
	  iss1 >> val;
	  if (i >= ret)
	    return (save);
	  save = val;
	  i = i + eff;
	}
    }
  else
    return (this->max / 2);
  std::cout << "merde" << std::endl;
  return (0);
}

void		Calc::mode(int val, int eff)
{
  if (this->tmp < eff)
    {
      this->tmp = eff;
      this->mod = val;
    }
}

void		Calc::variance(int val, int eff)
{
  this->var = (pow(val, 2) * eff) + this->var;
}

double		Calc::ecartMoyen(double arit)
{
  double       	tmp = 0;
  std::list<std::string>::iterator it;
  int		nbr = 0;
  double       	ret = 0;

  for (it = this->value.begin();it != this->value.end(); ++it)
    {
      if (nbr == 0)
	{
	  std::istringstream	iss(*it);
	  iss >> nbr;
	  ++it;
	}
      int		val = 0;
      int		eff = 0;
      std::stringstream	temp(*it);
      std::string	valeur;
      std::string	effectif;
      temp >> valeur;
      temp >> effectif;
      std::istringstream	iss1(valeur);
      std::istringstream	iss2(effectif);
      iss1 >> val;
      iss2 >> eff;
      tmp = (val - arit) * eff;
      ret = ret + fabs(tmp);
    }
  return (ret / this->total);
}

double		Calc::ecartMedian(double medi)
{
  double       	tmp = 0;
  std::list<std::string>::iterator it;
  int		nbr = 0;
  double       	ret = 0;

  for (it = this->value.begin();it != this->value.end(); ++it)
    {
      if (nbr == 0)
	{
	  std::istringstream	iss(*it);
	  iss >> nbr;
	  ++it;
	}
      int		val = 0;
      int		eff = 0;
      std::stringstream	temp(*it);
      std::string	valeur;
      std::string	effectif;
      temp >> valeur;
      temp >> effectif;
      std::istringstream	iss1(valeur);
      std::istringstream	iss2(effectif);
      iss1 >> val;
      iss2 >> eff;
      tmp = (val - medi) * eff;
      ret = ret + fabs(tmp);
    }
  return (ret / this->total);
}
